package com.yyfax.pay.third.facade.baofu;

import static com.yyfax.framework.yyfax.enums.RspCodeEnum.COMMON_ERROR_UNKNOWN_EXCEPTION;

import java.math.BigDecimal;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.yyfax.commons.json.JacksonUtil;
import com.yyfax.commons.lang.DateUtil;
import com.yyfax.pay.common.enums.PayModeEnum;
import com.yyfax.pay.common.enums.PayRspCodeEnum;
import com.yyfax.pay.common.enums.PayTypeEnum;
import com.yyfax.pay.common.enums.PaymentEnum;
import com.yyfax.pay.common.exception.YYPayException;
import com.yyfax.pay.config.data.service.BankConfigExtService;
import com.yyfax.pay.config.data.service.MerchantPaymentService;
import com.yyfax.pay.config.model.po.BankConfigExtPO;
import com.yyfax.pay.config.model.po.MerchantPaymentPO;
import com.yyfax.pay.order.data.service.PayOrderService;
import com.yyfax.pay.order.model.po.PayinOrderPO;
import com.yyfax.pay.order.model.to.payin.PayinBatchOrderYYContent;
import com.yyfax.pay.order.model.to.payin.PayinBatchVo;
import com.yyfax.pay.order.model.to.payin.PayinOrderYYContent;
import com.yyfax.pay.order.model.to.payin.PayinSnapshotVo;
import com.yyfax.pay.order.model.to.payin.QueryBatchPayinOrderYYContent;
import com.yyfax.pay.order.model.to.payin.QueryBatchPayinOrderYYContent.QueryPayinOrder;
import com.yyfax.pay.order.service.PayCommonService;
import com.yyfax.pay.third.model.to.baofu.PayinBatchOrderBaoFuContent;
import com.yyfax.pay.third.model.to.baofu.PayinBatchOrderBaoFuParams;
import com.yyfax.pay.third.model.to.baofu.PayinBatchOrderBaoFuParams.PayinBatchItem;
import com.yyfax.pay.third.model.to.baofu.PayinOrderBaoFuContent;
import com.yyfax.pay.third.model.to.baofu.PayinOrderBaoFuParams;
import com.yyfax.pay.third.model.to.baofu.QueryPayinBatchOrderBaoFuContent;
import com.yyfax.pay.third.model.to.baofu.QueryPayinBatchOrderBaoFuContent.QueryPayinBatchContentItem;
import com.yyfax.pay.third.model.to.baofu.QueryPayinBatchOrderBaoFuParams;
import com.yyfax.pay.third.model.to.baofu.QueryPayinOrderBaoFuContent;
import com.yyfax.pay.third.model.to.baofu.QueryPayinOrderBaoFuParams;
import com.yyfax.pay.third.model.to.yyfax.QueryCardBinContent;
import com.yyfax.pay.third.model.to.yyfax.payin.QueryPayinOrderYYContent;

/**
 * 宝付支付实体转换
 * 
 * @author maojian
 * @date 2017-05-3 10:52:53
 * @since v1.0.0
 */
@Service
public class BaoFuTransformService {

	@Autowired
	private MerchantPaymentService merchantPaymentService;

	@Autowired
	private PayOrderService payOrderService;
	
	@Autowired
	private BankConfigExtService bankConfigExtService;
	
	@Autowired
	private PayCommonService payCommonService;

	private Logger logger = LoggerFactory.getLogger(getClass());
	
	
	
	public PayinOrderBaoFuParams transformPayinOrderParam(PayinSnapshotVo payinchVo) throws Exception{
		final String OP = "【baofu】【transformPayinBatchOrderParam】查询支付通道信息";
		MerchantPaymentPO merchant = merchantPaymentService.queryByThirdMerchantCode(payinchVo.getMerchantCode(), PaymentEnum.BAOFU.getValue(),
				PayTypeEnum.PAY_IN.getValue(), PayModeEnum.AUTH_PAY.getValue());
		logger.info(OP + "成功,merchant:{}", JacksonUtil.nonullMapper.toJson(merchant));
		if (merchant == null) {
			logger.error(OP + "失败,商户信息为空,merchantCode:{}", payinchVo.getMerchantCode());
			throw new YYPayException(PayRspCodeEnum.PAY_CODE_PAY_FAIL.getValue(), "查询支付通道信息失败,商户信息为空.");
		}
		return buildPayinOrderBaoFuParams(merchant,payinchVo);
	}
	
	private PayinOrderBaoFuParams buildPayinOrderBaoFuParams(MerchantPaymentPO merchant, PayinSnapshotVo payin) throws Exception{
		PayinOrderBaoFuParams params = new PayinOrderBaoFuParams();
		if (StringUtils.isBlank(merchant.getExt())) {
			throw new YYPayException(PayRspCodeEnum.PAY_CODE_BATCH_PAYIN_FAIL.getValue(), "支付商户扩展信息为空");
		}
		JSONObject json = JSONObject.parseObject(merchant.getExt());
		params.setVersion(json.getString("version"));
		params.setBizType(json.getString("bizType"));
		params.setTerminalId(json.getString("terminalId"));
		params.setMemberId(json.getString("memberId"));
		params.setTxnType(json.getString("payinType"));
		params.setTxnSubType(json.getString("payinSubType"));
		params.setUrl(json.getString("url"));
		params.setPfxPath(json.getString("pfxPath"));
		params.setPfxPwd(json.getString("pfxPwd"));
		params.setCerPath(json.getString("cerPath"));
		params.setDataType(json.getString("dataType"));
		params.setTransId(payin.getPayinOrderId());
		params.setTransSerialNo(payin.getPayinOrderId());
		params.setTradeDate(DateUtil.date2Str(DateUtil.str2DateTime(payin.getOrderTime()),DateUtil.FORMAT_YYYYMMDDHHMMSS));
		params.setAccNo(payin.getPayerCardNo());
		params.setIdHolder(payin.getPayerName());
		params.setIdCardType(payin.getCertType());
		params.setIdCard(payin.getCertNo());
		params.setTxnAmt(String.valueOf(payin.getAmount()));
		params.setMobile(payin.getMobile());
		params.setPayCm(json.getString("payCm"));
		QueryCardBinContent cardBin = payCommonService.queryCardBin(payin.getMerchantCode(), payin.getPayerCardNo());
		BankConfigExtPO bankconfigExt = bankConfigExtService.queryByThirdBankCode(cardBin.getBankCode(), payin.getPaymentCode());
		params.setPayCode(bankconfigExt.getEnNameExt());
		return params;
	}
	
	public PayinBatchOrderBaoFuParams transformPayinBatchOrderParam(PayinBatchVo payinBatchVo) throws Exception{
		MerchantPaymentPO merchant = merchantPaymentService.queryByThirdMerchantCode(payinBatchVo.getMerchantCode(), PaymentEnum.BAOFU.getValue(),
				PayTypeEnum.BATCH_PAY_IN.getValue(), PayModeEnum.AUTH_PAY.getValue());
		logger.info("【baofu】【transformPayinBatchOrderParam】查询支付通过信息成功,merchant:{}", JacksonUtil.nonullMapper.toJson(merchant));
		if (merchant == null) {
			logger.error("【baofu】【transformPayinBatchOrderParam】查询支付通过信息失败,商户信息为空,merchantCode:{}", payinBatchVo.getMerchantCode());
			throw new YYPayException(PayRspCodeEnum.PAY_CODE_PAY_FAIL.getValue(), "查询支付通道信息失败,商户信息为空.");
		}
		return buildPayinBatchOrderBaoFuParams(merchant,payinBatchVo);
	}
	
	private PayinBatchOrderBaoFuParams buildPayinBatchOrderBaoFuParams(MerchantPaymentPO merchant, PayinBatchVo payinBatchVo) throws Exception{
		PayinBatchOrderBaoFuParams params = new PayinBatchOrderBaoFuParams();
		if (StringUtils.isBlank(merchant.getExt())) {
			throw new YYPayException(PayRspCodeEnum.PAY_CODE_BATCH_PAYIN_FAIL.getValue(), "支付商户扩展信息为空");
		}
		JSONObject json = JSONObject.parseObject(merchant.getExt());
		params.setVersion(json.getString("version"));
		params.setTerminalId(json.getString("terminalId"));
		params.setMemberId(json.getString("memberId"));
		params.setTxnType(json.getString("payinBatchType"));
		params.setTxnSubType(json.getString("payinBatchSubType"));
		params.setUrl(json.getString("url"));
		params.setTransBatchId(payinBatchVo.getPayinBatchOrderId());
		params.setTransSerialNo(payinBatchVo.getPayinBatchOrderId());
		params.setPfxPath(json.getString("pfxPath"));
		params.setPfxPwd(json.getString("pfxPwd"));
		params.setCerPath(json.getString("cerPath"));
		params.setDataType(json.getString("dataType"));
		List<PayinBatchItem> items = Lists.newArrayList();
		for(PayinOrderPO payin : payinBatchVo.getPayinOrderVOs()){
			PayinBatchItem  item =  new PayinBatchItem();
			item.setTransId(payin.getPayinOrderId());
			item.setTransDate(DateUtil.date2Str(DateUtil.str2DateTime(payin.getOrderTime()),DateUtil.FORMAT_YYYYMMDDHHMMSS));
			item.setAccNo(payin.getPayerCardNo());
			item.setIdHolder(payin.getPayerName());
			item.setIdCardType(payin.getCertType());
			item.setIdCard(payin.getCertNo());
			item.setTxnAmt(String.valueOf(payin.getAmount()));
			item.setMobile(payin.getMobile());
			items.add(item);
		}
		params.setItems(items);
		return 	params;
	}

	public PayinBatchOrderYYContent transformPayinBatchOrderContent(PayinBatchOrderBaoFuContent content){
		PayinBatchOrderYYContent yyContent = new PayinBatchOrderYYContent();
		String respCode = content.getRespCode();
		String respMsg = content.getRespMsg();
		if (respCode.equals(PayinBatchOrderBaoFuContent.SUCCESS)) {
			yyContent.setResultCode(PayRspCodeEnum.SUCCESS.getValue());
			yyContent.setResultMsg(respMsg);
		} else {
			yyContent.setResultCode(COMMON_ERROR_UNKNOWN_EXCEPTION.getValue());
			yyContent.setResultMsg(respMsg);
		}
		yyContent.setReqContent(content.getReqContent());
		yyContent.setRspContent(content.toString());
		yyContent.setOutBatchId(content.getBatchId());
		return yyContent;
	}
	
	public QueryBatchPayinOrderYYContent transformQueryPayinBatchOrderContent(QueryPayinBatchOrderBaoFuContent content){
		QueryBatchPayinOrderYYContent yyContent = new QueryBatchPayinOrderYYContent();
		String respCode = content.getRespCode();
		String respMsg = content.getRespMsg();
		Long successAmount = 0L;
		int successCount = 0;
		if (respCode.equals(PayinBatchOrderBaoFuContent.SUCCESS)) {
			yyContent.setResultCode(PayRspCodeEnum.SUCCESS.getValue());
			yyContent.setResultMsg(respMsg);
		} else {
			yyContent.setResultCode(COMMON_ERROR_UNKNOWN_EXCEPTION.getValue());
			yyContent.setResultMsg(respMsg);
		}
		yyContent.setReqContent(content.getReqContent());
		yyContent.setRspContent(content.toString());
		List<QueryPayinOrder> orders = Lists.newArrayList();
		for(QueryPayinBatchContentItem item :content.getItems()){
			QueryPayinOrder order = new QueryPayinOrder();
			if(item.getOrderStat().equals(QueryPayinOrder.SUCCESS)){
				order.setResultCode(PayRspCodeEnum.SUCCESS.getValue());
				int amount = new BigDecimal(item.getSuccAmt()).multiply(new BigDecimal("100")).intValue();
				order.setAmount(amount);
				successAmount+=amount;
				successCount++;
			}else if(item.getOrderStat().equals(QueryPayinOrder.FAILED)){
				order.setResultCode(PayRspCodeEnum.PAY_CODE_PAY_FAIL.getValue());
			}else if(item.getOrderStat().equals(QueryPayinOrder.ING)){
				order.setResultCode(PayRspCodeEnum.PAY_CODE_DEALING.getValue());
			}else{
				yyContent.setResultCode(COMMON_ERROR_UNKNOWN_EXCEPTION.getValue());
			}
			order.setResultMsg(item.getRespMsg());
			order.setPayinOrderId(item.getTransId());
			order.setSerialNo(item.getTransNo());
			orders.add(order);
			
		}
		yyContent.setSuccessAmount(successAmount);
		yyContent.setSuccessCount(successCount);
		yyContent.setQueryPayinOrders(orders);
		return yyContent;
	}
	
	
	public QueryPayinBatchOrderBaoFuParams transformQueryPayinBatchOrderParam(PayinBatchVo payinBatchVo) throws Exception{
		MerchantPaymentPO merchant = merchantPaymentService.queryByThirdMerchantCode(payinBatchVo.getMerchantCode(), PaymentEnum.BAOFU.getValue(),
				PayTypeEnum.BATCH_PAY_IN.getValue(), PayModeEnum.AUTH_PAY.getValue());
		logger.info("【baofu】【transformPayinBatchOrderParam】查询支付通过信息成功,merchant:{}", JacksonUtil.nonullMapper.toJson(merchant));
		if (merchant == null) {
			logger.error("【baofu】【transformPayinBatchOrderParam】查询支付通过信息失败,商户信息为空,merchantCode:{}", payinBatchVo.getMerchantCode());
			throw new YYPayException(PayRspCodeEnum.PAY_CODE_PAY_FAIL.getValue(), "查询支付通道信息失败,商户信息为空.");
		}
		return buildQueryPayinBatchOrderBaoFuParams(merchant,payinBatchVo);
	}
	
	private QueryPayinBatchOrderBaoFuParams buildQueryPayinBatchOrderBaoFuParams(MerchantPaymentPO merchant, PayinBatchVo payinBatchVo) throws Exception{
		QueryPayinBatchOrderBaoFuParams params = new QueryPayinBatchOrderBaoFuParams();
		if (StringUtils.isBlank(merchant.getExt())) {
			throw new YYPayException(PayRspCodeEnum.PAY_CODE_BATCH_PAYIN_FAIL.getValue(), "支付商户扩展信息为空");
		}
		JSONObject json = JSONObject.parseObject(merchant.getExt());
		params.setVersion(json.getString("version"));
		params.setTerminalId(json.getString("terminalId"));
		params.setMemberId(json.getString("memberId"));
		params.setTxnType(json.getString("payinBatchType"));
		params.setTxnSubType(json.getString("queryPayinBatchSubType"));
		params.setUrl(json.getString("url"));
		params.setTransBatchId(payinBatchVo.getPayinBatchOrderId());
		params.setTransSerialNo(String.valueOf(System.currentTimeMillis()));
		params.setPfxPath(json.getString("pfxPath"));
		params.setPfxPwd(json.getString("pfxPwd"));
		params.setCerPath(json.getString("cerPath"));
		params.setDataType(json.getString("dataType"));
		return 	params;
	}
	
	public QueryPayinOrderBaoFuParams transformQueryPayinOrderParams(PayinSnapshotVo req) throws Exception{
		MerchantPaymentPO merchant = merchantPaymentService.queryByThirdMerchantCode(req.getMerchantCode(), PaymentEnum.BAOFU.getValue(),
				PayTypeEnum.PAY_IN.getValue(), PayModeEnum.AUTH_PAY.getValue());
		logger.info("【baofu】【transformPayinBatchOrderParam】查询支付通过信息成功,merchant:{}", JacksonUtil.nonullMapper.toJson(merchant));
		if (merchant == null) {
			logger.error("【baofu】【transformPayinBatchOrderParam】查询支付通过信息失败,商户信息为空,merchantCode:{}", req.getMerchantCode());
			throw new YYPayException(PayRspCodeEnum.PAY_CODE_PAY_FAIL.getValue(), "查询支付通道信息失败,商户信息为空.");
		}
		return buildQueryPayinOrderBaoFuParams(merchant,req);
	}
	
	private QueryPayinOrderBaoFuParams buildQueryPayinOrderBaoFuParams(MerchantPaymentPO merchant, PayinSnapshotVo payinBatchVo) throws Exception{
		QueryPayinOrderBaoFuParams params = new QueryPayinOrderBaoFuParams();
		if (StringUtils.isBlank(merchant.getExt())) {
			throw new YYPayException(PayRspCodeEnum.PAY_CODE_BATCH_PAYIN_FAIL.getValue(), "支付商户扩展信息为空");
		}
		JSONObject json = JSONObject.parseObject(merchant.getExt());
		params.setVersion(json.getString("version"));
		params.setBizType(json.getString("bizType"));
		params.setTerminalId(json.getString("terminalId"));
		params.setMemberId(json.getString("memberId"));
		params.setTxnType(json.getString("payinType"));
		params.setTxnSubType(json.getString("queryPayinSubType"));
		params.setUrl(json.getString("url"));
		params.setTransBatchId(payinBatchVo.getPayinBatchOrderId());
		params.setTransSerialNo(String.valueOf(System.currentTimeMillis()));
		params.setPfxPath(json.getString("pfxPath"));
		params.setPfxPwd(json.getString("pfxPwd"));
		params.setCerPath(json.getString("cerPath"));
		params.setDataType(json.getString("dataType"));
		params.setOrigTransId(payinBatchVo.getPayinOrderId());
		params.setOrigTradeDate(DateUtil.date2Str(DateUtil.str2DateTime(payinBatchVo.getOrderTime()),DateUtil.FORMAT_YYYYMMDDHHMMSS));
		return 	params;
	}
 	
	public PayinOrderYYContent transformPayinOrderContent(PayinOrderBaoFuContent content){
		PayinOrderYYContent yyContent = new PayinOrderYYContent();
		String respCode = content.getRespCode();
		String respMsg = content.getRespMsg();
		if (respCode.equals(PayinBatchOrderBaoFuContent.SUCCESS)) {
			yyContent.setResultCode(PayRspCodeEnum.SUCCESS.getValue());
			yyContent.setResultMsg(respMsg);
		} else if(respCode.equals(PayinBatchOrderBaoFuContent.DUPLICATE)){
			yyContent.setResultCode(PayRspCodeEnum.PAY_CODE_ORDER_DUPLICATE.getValue());
			yyContent.setResultMsg(respMsg);
		}else {
			yyContent.setResultCode(COMMON_ERROR_UNKNOWN_EXCEPTION.getValue());
			yyContent.setResultMsg(respMsg);
		}
		yyContent.setSerialNo(content.getTransNo());
		yyContent.setReqContent(content.getReqContent());
		yyContent.setRspContent(content.toString());
		return yyContent;
	}
	
	public QueryPayinOrderYYContent transformQueryPayinOrderContent(QueryPayinOrderBaoFuContent content){
		QueryPayinOrderYYContent yyContent = new QueryPayinOrderYYContent();
		String respMsg = content.getRespMsg();
		String orderState = content.getOrderStat();
		if (orderState.equals(QueryPayinOrderYYContent.SUCCESS)) {
			yyContent.setResultCode(PayRspCodeEnum.SUCCESS.getValue());
			yyContent.setResultMsg(respMsg);
			yyContent.setSerialNo(content.getTransNo());
		} else if(orderState.equals(QueryPayinOrderYYContent.FAILED) || orderState.equals(QueryPayinOrderYYContent.FAILED2)){
			yyContent.setResultCode(PayRspCodeEnum.PAY_CODE_PAY_FAIL.getValue());
			yyContent.setResultMsg(PayRspCodeEnum.PAY_CODE_PAY_FAIL.getDisplay());
		} else if(orderState.equals(QueryPayinOrderYYContent.ING) ){
			yyContent.setResultCode(PayRspCodeEnum.PAY_CODE_DEALING.getValue());
			yyContent.setResultMsg(PayRspCodeEnum.PAY_CODE_DEALING.getDisplay());
		} else {
			yyContent.setResultCode(PayRspCodeEnum.PAY_CODE_QUERY_ORDER_FAIL.getValue());
			yyContent.setResultMsg(PayRspCodeEnum.PAY_CODE_QUERY_ORDER_FAIL.getDisplay());
		}
		yyContent.setReqContent(content.getReqContent());
		yyContent.setRspContent(content.toString());
		return yyContent;
	}
	
}
